package com.mnt.gui.base.contorls.table;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;

/**
 * 
 * <p>
 * 分页栏
 * </p>
 * 
 * @author Cico.Jiang
 * @version 2014年4月1日 下午5:38:57 Cico.Jiang .
 * @since 3.3
 */
public abstract class PagingBar extends HBox
{
	/**
	 * default max size is 10
	 */
	private static final int DEFAULT_DISPLAY_MAX_SIZE = 10;
	private static final byte LEFT = 0;
	private static final byte RIGHT = 1;
	private static final byte SWICH = 2;

	private SimpleIntegerProperty totalPageCount = new SimpleIntegerProperty(0);
	private int displayCount;
	private SimpleIntegerProperty currentIndex = new SimpleIntegerProperty(0); // 分页从1开始
	private Button btnLeft = new Button();
	private HBox hbIndex = new HBox();
	private Button btnRight = new Button();
	private ToggleGroup isSelected = new ToggleGroup();
	private Label lblTotal = new Label();
	private TextField txtToPage = new TextField();
	private Button btnGo = new Button("Go");
	private List<SingleSelectButton> indexButtonList = new ArrayList<SingleSelectButton>();
	private Map<Integer, SingleSelectButton> indexButtonMap = new HashMap<Integer, SingleSelectButton>();
	private byte leftOrRight;

	public PagingBar(int totalCount, int displayCount)
	{
		totalPageCount.addListener((obs, oldValue, newValue) -> {
			lblTotal.setText("共" + newValue + "页");
			if (displayCount == 0)
			{
				this.displayCount = DEFAULT_DISPLAY_MAX_SIZE;
			}
			if (totalCount <= displayCount)
			{
				btnRight.setDisable(true);
				this.displayCount = totalCount;
			}
			if (displayCount > DEFAULT_DISPLAY_MAX_SIZE)
			{
				btnRight.setDisable(false);
				this.displayCount = DEFAULT_DISPLAY_MAX_SIZE;
			}
			buildIndex();
		});
		configure();
		this.totalPageCount.set(totalCount);
		this.displayCount = displayCount;
	}

	public PagingBar(int totalCount)
	{
		this(totalCount, DEFAULT_DISPLAY_MAX_SIZE);
	}

	/**
	 * <p>
	 * 配置表格 css 样式 按钮事件
	 * </p>
	 * @since 2014年4月2日 上午10:31:38 Cico.Jiang
	 */
	private void configure()
	{
		this.getStylesheets().add(PagingBar.class.getResource("css/PagingBar.css").toExternalForm());
		this.getChildren().clear();
		this.setAlignment(Pos.CENTER);
		this.setSpacing(3);
		hbIndex.setAlignment(Pos.CENTER_LEFT);
		hbIndex.setSpacing(3);
		btnLeft.getStyleClass().add("btn-left");
		btnRight.getStyleClass().add("btn-right");
		txtToPage.setPrefWidth(40);
		btnGo.getStyleClass().add("btn-go");
		this.getChildren().addAll(lblTotal,btnLeft, hbIndex, btnRight, txtToPage , btnGo);
		EventHandler<ActionEvent> swichPageAction = new EventHandler<ActionEvent>()
		{
			@Override
			public void handle(ActionEvent event)
			{
				int index = currentIndex.get();
				try
				{
					index = Integer.parseInt(txtToPage.getText());
					if(index > totalPageCount.get()) {
						index = currentIndex.get();
						txtToPage.setText(String.valueOf(index));
					}
				} catch (ClassCastException e)
				{
					txtToPage.setText(String.valueOf(index));
				}
				leftOrRight = SWICH;
				currentIndex.set(index);
			}
		};
		txtToPage.setOnAction(swichPageAction);
		btnGo.setOnAction(swichPageAction);
		
		btnLeft.setOnAction(new EventHandler<ActionEvent>()
		{

			@Override
			public void handle(ActionEvent event)
			{
				leftOrRight = LEFT;
				currentIndex.set(currentIndex.get() - 1);
			}
		});
		btnRight.setOnAction(new EventHandler<ActionEvent>()
		{

			@Override
			public void handle(ActionEvent event)
			{
				leftOrRight = RIGHT;
				currentIndex.set(currentIndex.get() + 1);
			}
		});
		currentIndex.addListener(new ChangeListener<Number>()
		{
			@Override
			public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue)
			{
				int value = newValue.intValue();
				if (value == 1)
				{
					btnLeft.setDisable(true);
				} else if (value == totalPageCount.get())
				{
					btnRight.setDisable(true);
				} else
				{
					btnLeft.setDisable(false);
					btnRight.setDisable(false);
				}
				clickIndex(value);
				if (indexButtonMap.containsKey(value))
				{ // 如果map中有则切换显示的索引
					indexButtonMap.get(value).setSelected(true);
				} else
				{
					updateIndex();
					if (indexButtonMap.containsKey(value))
					{
						indexButtonMap.get(value).setSelected(true);
					}
				}
			}
		});
	}

	/**
	 * 
	 * 初始化分页按钮
	 * <p>
	 * 初始化分页按钮并选中第一行
	 * </p>
	 * 
	 * @since 2014年4月1日 下午4:07:02 Cico.Jiang
	 */
	private void buildIndex()
	{
		SingleSelectButton singleSelectButton = null;
		indexButtonList.clear();
		hbIndex.getChildren().clear();
		indexButtonMap.clear();
		for (int i = 0; i < displayCount; i++)
		{
			singleSelectButton = new SingleSelectButton(i + 1);
			singleSelectButton.getStyleClass().add("btn-selectend");
			indexButtonList.add(singleSelectButton);
			singleSelectButton.setToggleGroup(isSelected);
			hbIndex.getChildren().add(singleSelectButton);
			indexButtonMap.put(i + 1, singleSelectButton);
		}
		btnLeft.setDisable(true);
		if(indexButtonList.size() > currentIndex.get()) {
			indexButtonList.get(currentIndex.get()).setSelected(true);
		}
	}

	/**
	 * 
	 * 点击到最后一列或者最前一列时重新刷新索引
	 * <p>
	 * 改变当页显示的索引
	 * </p>
	 * 
	 * @since 2014年4月1日 下午2:01:48 Cico.Jiang
	 */
	private void updateIndex()
	{
		indexButtonMap.clear();
		final int index = indexButtonList.get(0).getIndex();
		for (SingleSelectButton singleSelectButton : indexButtonList)
		{
			int newIndex = 0;
			switch (leftOrRight)
			{
			case LEFT:
				newIndex = singleSelectButton.getIndex() - displayCount;
				break;

			case RIGHT:
				newIndex = singleSelectButton.getIndex() + displayCount;
				break;
			case SWICH:
				newIndex = singleSelectButton.getIndex() + currentIndex.get() - index; 
				break;
			}
			singleSelectButton.setIndex(newIndex);
			indexButtonMap.put(newIndex, singleSelectButton);
			if(newIndex > totalPageCount.get()) {
				singleSelectButton.setDisable(true);
			} else {
				singleSelectButton.setDisable(false);
			}
		}
	}

	/**
	 * 
	 * <p>
	 * 选择某一个index 只要不和上一个 index重复就会执行这个方法
	 * </p>
	 * 
	 * @since 2014年4月1日 下午2:31:17 Cico.Jiang
	 * @param index
	 */
	protected abstract void clickIndex(int index);
	
	protected void setTotalCount(int totalCount) {
		totalPageCount.set(totalCount);
	}

	/**
	 * <p>
	 * 单选toggle button
	 * </p>
	 * 
	 * @author Cico.Jiang
	 * @version 2014年4月1日 下午2:25:16 Cico.Jiang .
	 * @since 3.3
	 */
	private class SingleSelectButton extends ToggleButton
	{
		private SingleSelectButton(int index)
		{
			this.setText(String.valueOf(index));
			this.setOnAction(new EventHandler<ActionEvent>()
			{
				@Override
				public void handle(ActionEvent event)
				{
					setSelected(true);
				}
			});
			final InvalidationListener firstSelect = new InvalidationListener()
			{

				@Override
				public void invalidated(Observable observable)
				{
					currentIndex.set(getIndex());
				}
			};
			this.selectedProperty().addListener(firstSelect);
			this.selectedProperty().addListener(new ChangeListener<Boolean>()
			{
				@Override
				public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue)
				{
					selectedProperty().removeListener(firstSelect);
					if (newValue)
					{
						currentIndex.set(getIndex());
					}
				}
			});
		}

		/**
		 * 
		 * 设置按钮上面的索引
		 * 
		 * @since 2014年4月1日 下午5:31:45 Cico.Jiang
		 * @param index
		 */
		private void setIndex(int index)
		{
			setText(String.valueOf(index));
		}

		/**
		 * 
		 * <p>
		 * 获取按钮的索引
		 * </p>
		 * 
		 * @since 2014年4月1日 下午5:32:04 Cico.Jiang
		 * @return
		 */
		private int getIndex()
		{
			return Integer.parseInt(this.getText());
		}
	}
}
